package com.shlh.saas.service.linkedin.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shlh.saas.common.Desensitization;
import com.shlh.saas.entity.facebook.EsFacebookFields;
import com.shlh.saas.entity.facebook.FacebookUserEs;
import com.shlh.saas.entity.linkedin.EsLinkedInFields;
import com.shlh.saas.entity.linkedin.LinkedInUserEs;
import com.shlh.saas.entity.twitter.TwitterUserEs;
import com.shlh.saas.es.EsIndexInfo;
import com.shlh.saas.es.EsRestClient;
import com.shlh.saas.es.EsSearchRequest;
import com.shlh.saas.model.dto.LinkedInQueryDTO;
import com.shlh.saas.service.linkedin.LinkedInEsService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.Collection;

/**
 * LinkedIn Elasticsearch服务实现类
 */
@Service
@Slf4j
public class LinkedInEsServiceImpl implements LinkedInEsService {

    @Resource
    private Desensitization desensitization;

    @Override
    public Page<LinkedInUserEs> queryLinkedInUserList(LinkedInUserEs req, Integer page, Integer size) {
        Page<LinkedInUserEs> pageResult = new Page<>();

        try {
            // 使用基础查询构建器
            BoolQueryBuilder bq = buildBaseQuery(req);

            // 设置分页参数
            long currentPage = Math.max(page, 1);
            long pageSize = size > 0 ? size : 10;
            long from = (currentPage - 1) * pageSize;

            // 构建ES请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(bq);
            esSearchRequest.setFields(EsLinkedInFields.FIELD_QUERY);
            esSearchRequest.setFrom(from);
            esSearchRequest.setSize(pageSize);
            esSearchRequest.setNeedScroll(false);

            SearchResponse searchResponse =
                    EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);
            List<LinkedInUserEs> linkedInUserEsList = new LinkedList<>();
            SearchHits searchHits = null;
            if (searchResponse != null) {
                searchHits = searchResponse.getHits();
            }
            if (searchHits == null || searchHits.getHits() == null) {
                pageResult.setTotal(0);
                pageResult.setSize(pageSize);
                pageResult.setRecords(linkedInUserEsList);
                return pageResult;
            }

            SearchHit[] hits = searchHits.getHits();
            log.debug("ES查询返回{}条结果", hits.length);

            for (SearchHit hit : hits) {
                LinkedInUserEs linkedInUserEs = convertResult(hit);
                if (Objects.nonNull(linkedInUserEs)) {
                    linkedInUserEsList.add(linkedInUserEs);
                }
            }

            // 当前页码 - 使用计算后的值
            pageResult.setCurrent(currentPage);
            // 每页大小 - 使用计算后的值
            pageResult.setSize(pageSize);
            pageResult.setRecords(linkedInUserEsList);
            // 总记录数
            pageResult.setTotal(searchHits.getTotalHits().value);

            return pageResult;

        } catch (Exception e) {
            log.error("ES查询LinkedIn用户列表失败", e);
            pageResult.setTotal(0);
            pageResult.setSize(size);
            pageResult.setRecords(new ArrayList<>());
            return pageResult;
        }
    }

    @Override
    public long countLinkedInUsers(LinkedInUserEs linkedInUserEs) {
        try {
            log.info("🔍 开始ES计数查询: linkedInUserEs={}", JSON.toJSONString(linkedInUserEs));

            // 1. 构建计数请求
            EsSearchRequest esCountRequest = createEsCountRequest(linkedInUserEs);

            // 2. 执行计数查询
            SearchResponse searchResponse =
                    EsRestClient.searchWithTermQuery(getEsIndexInfo(), esCountRequest);

            // 3. 获取并返回精确计数
            long totalCount = searchResponse.getHits().getTotalHits().value;
            String relation = searchResponse.getHits().getTotalHits().relation.toString();

            log.info("🔍 ES计数查询结果: totalCount={}, relation={}, trackTotalHits生效={}",
                    totalCount, relation, esCountRequest.isTrackTotalHits());

            return totalCount;

        } catch (Exception e) {
            log.error("ES计数查询失败", e);
            return 0L;
        }
    }

    @Override
    public Map<String, List<String>> queryLinkedInUserMapList(LinkedInUserEs req) {
        Map<String, List<String>> mapList = new HashMap<>();
        List<String> industries = new ArrayList<>();
        List<String> locations = new ArrayList<>();
        List<String> companySizes = new ArrayList<>();
        List<String> countries = new ArrayList<>();

        try {
            BoolQueryBuilder bq = buildBaseQuery(req);
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(bq);
            esSearchRequest.setFields(EsLinkedInFields.FIELD_QUERY);
            esSearchRequest.setFrom(0L);
            esSearchRequest.setSize(1000L); // 获取更多数据用于筛选选项
            esSearchRequest.setNeedScroll(false);

            SearchResponse searchResponse =
                    EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse != null && searchResponse.getHits() != null) {
                SearchHit[] hits = searchResponse.getHits().getHits();
                Set<String> industrySet = new HashSet<>();
                Set<String> locationSet = new HashSet<>();
                Set<String> companySizeSet = new HashSet<>();
                Set<String> countrySet = new HashSet<>();

                for (SearchHit hit : hits) {
                    Map<String, Object> sourceMap = hit.getSourceAsMap();

                    // 收集行业信息
                    Object industry = sourceMap.get(EsLinkedInFields.COMPANY_INDUSTRY);
                    if (industry != null && StringUtils.hasText(industry.toString())) {
                        industrySet.add(industry.toString());
                    }

                    // 收集位置信息
                    Object location = sourceMap.get(EsLinkedInFields.LOCATION);
                    if (location != null && StringUtils.hasText(location.toString())) {
                        locationSet.add(location.toString());
                    }

                    // 收集公司规模信息
                    Object companySize = sourceMap.get(EsLinkedInFields.COMPANY_SIZE);
                    if (companySize != null && StringUtils.hasText(companySize.toString())) {
                        companySizeSet.add(companySize.toString());
                    }

                    // 收集国家信息
                    Object country = sourceMap.get(EsLinkedInFields.COUNTRY);
                    if (country != null && StringUtils.hasText(country.toString())) {
                        countrySet.add(country.toString());
                    }
                }

                industries.addAll(industrySet);
                locations.addAll(locationSet);
                companySizes.addAll(companySizeSet);
                countries.addAll(countrySet);
            }

        } catch (Exception e) {
            log.error("获取LinkedIn用户筛选选项失败", e);
        }

        mapList.put("industries", industries);
        mapList.put("locations", locations);
        mapList.put("companySizes", companySizes);
        mapList.put("countries", countries);

        return mapList;
    }

    // ==================== 两阶段查询实现 ====================

    @Override
    public List<Map<String, String>> searchByCompanyAndJob(String companyName, String jobTitle, int limit) {
        log.info("ES两阶段查询 - 公司+职位: companyName={}, jobTitle={}, limit={}",
                companyName, jobTitle, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 公司名称匹配（必须条件）
            if (companyName != null && !companyName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_NAME, companyName));
            }

            // 职位匹配（必须条件）
            if (jobTitle != null && !jobTitle.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.JOB_TITLE, jobTitle));
            }

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - 公司+职位: companyName={}, jobTitle={}, error={}",
                    companyName, jobTitle, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByNameAndCompany(String firstName, String lastName, String companyName, int limit) {
        log.info("ES两阶段查询 - 姓名+公司: firstName={}, lastName={}, companyName={}, limit={}",
                firstName, lastName, companyName, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 名字匹配
            if (firstName != null && !firstName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.FIRST_NAME, firstName));
            }

            // 姓氏匹配
            if (lastName != null && !lastName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.LAST_NAME, lastName));
            }

            // 公司名称匹配
            if (companyName != null && !companyName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_NAME, companyName));
            }

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - 姓名+公司: firstName={}, lastName={}, companyName={}, error={}",
                    firstName, lastName, companyName, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByNameAndEmail(String firstName, String lastName, String email, int limit) {
        log.info("ES两阶段查询 - 姓名+邮箱: firstName={}, lastName={}, email={}, limit={}",
                firstName, lastName, email, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 名字匹配
            if (firstName != null && !firstName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.FIRST_NAME, firstName));
            }

            // 姓氏匹配
            if (lastName != null && !lastName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.LAST_NAME, lastName));
            }

            // 邮箱精确匹配
            if (email != null && !email.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.EMAILS, email.toLowerCase()));
            }

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - 姓名+邮箱: firstName={}, lastName={}, email={}, error={}",
                    firstName, lastName, email, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByPhoneAndName(String phoneNumber, String firstName, String lastName, int limit) {
        log.info("ES两阶段查询 - 手机号+姓名: phoneNumber={}, firstName={}, lastName={}, limit={}",
                phoneNumber, firstName, lastName, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 手机号精确匹配
            if (phoneNumber != null && !phoneNumber.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.MOBILE, phoneNumber));
            }

            // 名字匹配
            if (firstName != null && !firstName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.FIRST_NAME, firstName));
            }

            // 姓氏匹配
            if (lastName != null && !lastName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.LAST_NAME, lastName));
            }

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - 手机号+姓名: phoneNumber={}, firstName={}, lastName={}, error={}",
                    phoneNumber, firstName, lastName, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByEmail(String email, int limit, int offset) {
        log.info("ES两阶段查询 - 邮箱精确匹配: email={}, limit={}, offset={}", email, limit, offset);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 邮箱精确匹配（必须条件）
            if (email != null && !email.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.EMAILS, email.toLowerCase()));
            }

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), offset);

        } catch (Exception e) {
            log.error("ES查询失败 - 邮箱精确匹配: email={}, error={}", email, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByPhone(String phone, int size, int offset) {
        log.info("ES两阶段查询 - 邮箱精确匹配: phone={}, limit={}, offset={}", phone, size, offset);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 邮箱精确匹配（必须条件）
            if (phone != null && !phone.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.PHONE_NUMBERS, phone.toLowerCase()));
            }

            return executeEsSearchForIdentifiers(boolQuery, Math.min(size, 50), offset);

        } catch (Exception e) {
            log.error("ES查询失败 - 邮箱精确匹配: phone={}, error={}", phone, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByLinkedInUrl(String linkedinUrl, int limit) {
        log.info("ES两阶段查询 - LinkedIn URL: linkedinUrl={}, limit={}", linkedinUrl, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // LinkedIn URL精确匹配（必须条件）
            if (linkedinUrl != null && !linkedinUrl.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.LINKEDIN_URL, linkedinUrl));
            }

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - LinkedIn URL: linkedinUrl={}, error={}", linkedinUrl, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    // ==================== 导出功能两阶段查询实现 ====================

    @Override
    public List<Map<String, String>> searchForExport(LinkedInQueryDTO queryDTO, int limit) {
        log.info("ES两阶段查询 - 导出数据: queryDTO={}, limit={}", queryDTO, limit);

        try {
            // 对于大数据量导出，使用分批查询策略，避免单次查询超时
            if (limit > 10000) {
                log.info("检测到大数据量导出请求({}条)，启用分批查询策略", limit);
                return searchForExportWithBatching(queryDTO, limit);
            } else {
            BoolQueryBuilder boolQuery = buildExportQuery(queryDTO);
                return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 1000000), 0); 
            }
        } catch (Exception e) {
            log.error("ES导出查询失败: queryDTO={}, error={}", queryDTO, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 使用分批策略进行大数据量导出查询
     * 将大查询拆分为多个小批次，避免单次查询超时
     */
    private List<Map<String, String>> searchForExportWithBatching(LinkedInQueryDTO queryDTO, int limit) {
        log.info("开始分批查询ES数据，总数量: {}", limit);
        List<Map<String, String>> allResults = new ArrayList<>();
        BoolQueryBuilder boolQuery = buildExportQuery(queryDTO);
        
        // 每批大小，避免单次查询过大
        int batchSize = 5000; 
        int totalBatches = (int) Math.ceil((double) limit / batchSize);
        
        log.info("分批查询计划: 总批次={}，每批大小={}", totalBatches, batchSize);
        
        for (int batchNum = 0; batchNum < totalBatches; batchNum++) {
            int offset = batchNum * batchSize;
            int currentBatchSize = Math.min(batchSize, limit - offset);
            
            if (currentBatchSize <= 0) {
                break; // 已经获取了所有需要的数据
            }
            
            log.info("执行第 {}/{} 批查询，偏移量: {}, 大小: {}", 
                    batchNum + 1, totalBatches, offset, currentBatchSize);
            
            try {
                List<Map<String, String>> batchResults = 
                        executeEsSearchForIdentifiersWithPagination(boolQuery, offset, currentBatchSize);
                
                if (batchResults.isEmpty()) {
                    log.warn("第 {}/{} 批查询返回空结果，可能已到达数据末尾", batchNum + 1, totalBatches);
                    break;
                }
                
                allResults.addAll(batchResults);
                log.info("第 {}/{} 批查询完成，获取 {} 条记录，累计: {}/{}",
                        batchNum + 1, totalBatches, batchResults.size(), allResults.size(), limit);
                
                // 如果已经获取了足够的数据，就停止
                if (allResults.size() >= limit) {
                    log.info("已达到要求的数据量 ({})，停止批量查询", limit);
                    break;
                }
                
            } catch (Exception e) {
                log.error("第 {}/{} 批查询失败: {}", batchNum + 1, totalBatches, e.getMessage(), e);
                // 继续下一批查询，而不是完全失败
            }
        }
        
        // 如果需要，截断到要求的长度
        if (allResults.size() > limit) {
            allResults = allResults.subList(0, limit);
        }
        
        log.info("分批查询完成，总共获取 {} 条记录", allResults.size());
        return allResults;
    }

    @Override
    public List<Map<String, String>> searchForExportWithPagination(LinkedInQueryDTO queryDTO, int from, int size) {
        log.info("ES两阶段查询 - 分页导出数据: queryDTO={}, from={}, size={}", queryDTO, from, size);

        try {
            BoolQueryBuilder boolQuery = buildExportQuery(queryDTO);
            return executeEsSearchForIdentifiersWithPagination(boolQuery, from, size);

        } catch (Exception e) {
            log.error("ES分页导出查询失败: queryDTO={}, from={}, size={}, error={}", queryDTO, from, size, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    // ==================== 关键词搜索实现 ====================

    @Override
    public Page<LinkedInUserEs> searchWithFilters(String keyword, String companyName, String jobTitle,
                                                  String industry, String location, String contactMethod,
                                                  String companySize, int from, int size) {
        log.info("ES筛选搜索: keyword={}, companyName={}, jobTitle={}, industry={}, location={}, contactMethod={}, companySize={}, from={}, size={}",
                keyword, companyName, jobTitle, industry, location, contactMethod, companySize, from, size);

        try {
            BoolQueryBuilder boolQuery = buildFilterQuery(keyword, companyName, jobTitle, industry, location, contactMethod, companySize);

            // 构建ES请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFields(EsLinkedInFields.FIELD_QUERY);
            esSearchRequest.setFrom((long) from);
            esSearchRequest.setSize((long) size);
            esSearchRequest.setNeedScroll(false);

            // 添加排序
            esSearchRequest.setSortName(EsLinkedInFields.SORT_FIELD_PRIMARY);
            esSearchRequest.setSortOrder(EsLinkedInFields.SORT_ORDER_NEWEST_FIRST);

            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            Page<LinkedInUserEs> pageResult = new Page<>();
            List<LinkedInUserEs> linkedInUserEsList = new ArrayList<>();

            if (searchResponse != null && searchResponse.getHits() != null) {
                SearchHit[] hits = searchResponse.getHits().getHits();
                for (SearchHit hit : hits) {
                    LinkedInUserEs linkedInUserEs = convertResult(hit);
                    if (linkedInUserEs != null) {
                        desensitizationLinkedIn(linkedInUserEs);
                        linkedInUserEsList.add(linkedInUserEs);
                    }
                }
                pageResult.setTotal(searchResponse.getHits().getTotalHits().value);
            } else {
                pageResult.setTotal(0);
            }

            pageResult.setRecords(linkedInUserEsList);
            pageResult.setCurrent(from / size + 1);
            pageResult.setSize(size);

            return pageResult;

        } catch (Exception e) {
            log.error("ES筛选搜索失败", e);
            Page<LinkedInUserEs> pageResult = new Page<>();
            pageResult.setTotal(0);
            pageResult.setRecords(new ArrayList<>());
            pageResult.setCurrent(from / size + 1);
            pageResult.setSize(size);
            return pageResult;
        }
    }


    private void desensitizationLinkedIn(LinkedInUserEs linkedInUserEs) {
        if (StringUtils.hasText(linkedInUserEs.getEmails())){
            linkedInUserEs.setEmails(desensitization.maskEmail(linkedInUserEs.getEmails()));
        }

        if (StringUtils.hasText(linkedInUserEs.getPhoneNumbers())){
            linkedInUserEs.setPhoneNumbers(desensitization.maskPhone(linkedInUserEs.getPhoneNumbers()));
        }

        if (StringUtils.hasText(linkedInUserEs.getMobile())){
            linkedInUserEs.setMobile(desensitization.maskPhone(linkedInUserEs.getMobile()));
        }

        if (StringUtils.hasText(linkedInUserEs.getLinkedinUrl())){
            linkedInUserEs.setLinkedinUrl(desensitization.maskWebAddress(linkedInUserEs.getLinkedinUrl()));
        }

        if (StringUtils.hasText(linkedInUserEs.getCompanyWebsite())){
            linkedInUserEs.setCompanyWebsite(desensitization.maskWebAddress(linkedInUserEs.getCompanyWebsite()));
        }

        if (StringUtils.hasText(linkedInUserEs.getFacebookUrl())){
            linkedInUserEs.setFacebookUrl(desensitization.maskWebAddress(linkedInUserEs.getFacebookUrl()));
        }

        if (StringUtils.hasText(linkedInUserEs.getTwitterUrl())){
            linkedInUserEs.setTwitterUrl(desensitization.maskWebAddress(linkedInUserEs.getTwitterUrl()));
        }

        if (StringUtils.hasText(linkedInUserEs.getGithubUrl())){
            linkedInUserEs.setGithubUrl(desensitization.maskWebAddress(linkedInUserEs.getGithubUrl()));
        }
    }

    @Override
    public long countWithFilters(String keyword, String companyName, String jobTitle,
                                 String industry, String location, String contactMethod,
                                 String companySize) {
        log.info("ES筛选计数: keyword={}, companyName={}, jobTitle={}, industry={}, location={}, contactMethod={}, companySize={}",
                keyword, companyName, jobTitle, industry, location, contactMethod, companySize);

        try {
            BoolQueryBuilder boolQuery = buildFilterQuery(keyword, companyName, jobTitle, industry, location, contactMethod, companySize);

            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom(0L);
            esSearchRequest.setSize(0L); // 只计数，不返回数据
            esSearchRequest.setNeedScroll(false);
            esSearchRequest.setTrackTotalHits(true); // 确保获取精确计数

            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse != null && searchResponse.getHits() != null) {
                return searchResponse.getHits().getTotalHits().value;
            }

            return 0L;

        } catch (Exception e) {
            log.error("ES筛选计数失败", e);
            return 0L;
        }
    }

    @Override
    public List<String> getSuggestions(String keyword, String field, int limit) {
        // 简化实现，返回空列表，可以后续扩展
        return new ArrayList<>();
    }

    @Override
    public Map<String, Long> getIndustryDistribution(LinkedInUserEs queryCondition) {
        // 简化实现，返回空映射，可以后续扩展
        return new HashMap<>();
    }

    @Override
    public Map<String, Long> getLocationDistribution(LinkedInUserEs queryCondition) {
        // 简化实现，返回空映射，可以后续扩展
        return new HashMap<>();
    }

    @Override
    public Map<String, Long> getCompanySizeDistribution(LinkedInUserEs queryCondition) {
        // 简化实现，返回空映射，可以后续扩展
        return new HashMap<>();
    }

    @Override
    public List<LinkedInUserEs> searchLinkedInUsersWithEmail(String searchKeyword, int offset, int size) {

        LinkedInUserEs linkedInUserEs = new LinkedInUserEs();
        linkedInUserEs.setFullName(searchKeyword);
        linkedInUserEs.setCompanyWebsite(searchKeyword);
        linkedInUserEs.setCompanyName(searchKeyword);
        linkedInUserEs.setContactMethod("email");

        // 使用基础查询构建器
        BoolQueryBuilder bq = buildWithEmailAndPhoneQuery(linkedInUserEs);

        // 设置分页参数
        long pageSize = size > 0 ? size : 10;

        // 构建ES请求
        EsSearchRequest esSearchRequest = new EsSearchRequest();
        esSearchRequest.setBq(bq);
        esSearchRequest.setFields(EsLinkedInFields.FIELD_QUERY);
        esSearchRequest.setFrom((long) offset);
        esSearchRequest.setSize(pageSize);
        esSearchRequest.setNeedScroll(false);

        SearchResponse searchResponse =
                EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);
        List<LinkedInUserEs> linkedInUserEsList = new LinkedList<>();
        SearchHits searchHits = null;
        if (searchResponse != null) {
            searchHits = searchResponse.getHits();
        }
        if (searchHits == null || searchHits.getHits() == null) {
            return linkedInUserEsList;
        }

        SearchHit[] hits = searchHits.getHits();
        log.debug("ES查询返回{}条结果", hits.length);

        for (SearchHit hit : hits) {
            LinkedInUserEs linkedInEs = convertResult(hit);
            if (Objects.nonNull(linkedInEs)) {
                linkedInUserEsList.add(linkedInEs);
            }
        }
        return linkedInUserEsList;
    }

    @Override
    public Long countLinkedInUsersWithEmail(String searchKeyword) {
        LinkedInUserEs linkedInUserEs = new LinkedInUserEs();
        linkedInUserEs.setFullName(searchKeyword);
        linkedInUserEs.setCompanyWebsite(searchKeyword);
        linkedInUserEs.setCompanyName(searchKeyword);
        linkedInUserEs.setContactMethod("email");

        // 使用基础查询构建器
        BoolQueryBuilder bq = buildWithEmailAndPhoneQuery(linkedInUserEs);

        // 构建ES请求
        EsSearchRequest esSearchRequest = new EsSearchRequest();
        esSearchRequest.setBq(bq);
        esSearchRequest.setFields(EsLinkedInFields.FIELD_QUERY);
        esSearchRequest.setFrom(0L);
        esSearchRequest.setSize(0L);
        esSearchRequest.setNeedScroll(false);
        esSearchRequest.setTrackTotalHits(true); // 确保获取精确计数

        SearchResponse searchResponse =
                EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

        if (searchResponse != null) {
            return Objects.requireNonNull(searchResponse.getHits().getTotalHits()).value;
        }

        return 0L;
    }

    @Override
    public List<LinkedInUserEs> searchLinkedInUsersWithPhone(String searchKeyword, int offset, int size) {
        LinkedInUserEs linkedInUserEs = new LinkedInUserEs();
        linkedInUserEs.setFullName(searchKeyword);
        linkedInUserEs.setCompanyWebsite(searchKeyword);
        linkedInUserEs.setCompanyName(searchKeyword);
        linkedInUserEs.setContactMethod("phone");

        // 使用基础查询构建器
        BoolQueryBuilder bq = buildWithEmailAndPhoneQuery(linkedInUserEs);

        // 设置分页参数
        long pageSize = size > 0 ? size : 10;

        // 构建ES请求
        EsSearchRequest esSearchRequest = new EsSearchRequest();
        esSearchRequest.setBq(bq);
        esSearchRequest.setFields(EsLinkedInFields.FIELD_QUERY);
        esSearchRequest.setFrom((long) offset);
        esSearchRequest.setSize(pageSize);
        esSearchRequest.setNeedScroll(false);

        SearchResponse searchResponse =
                EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);
        List<LinkedInUserEs> linkedInUserEsList = new LinkedList<>();
        SearchHits searchHits = null;
        if (searchResponse != null) {
            searchHits = searchResponse.getHits();
        }
        if (searchHits == null || searchHits.getHits() == null) {
            return linkedInUserEsList;
        }

        SearchHit[] hits = searchHits.getHits();
        log.debug("ES查询返回{}条结果", hits.length);

        for (SearchHit hit : hits) {
            LinkedInUserEs linkedInEs = convertResult(hit);
            if (Objects.nonNull(linkedInEs)) {
                linkedInUserEsList.add(linkedInEs);
            }
        }
        return linkedInUserEsList;
    }

    @Override
    public Long countLinkedInUsersWithPhone(String searchKeyword) {
        LinkedInUserEs linkedInUserEs = new LinkedInUserEs();
        linkedInUserEs.setFullName(searchKeyword);
        linkedInUserEs.setCompanyWebsite(searchKeyword);
        linkedInUserEs.setCompanyName(searchKeyword);
        linkedInUserEs.setContactMethod("phone");

        // 使用基础查询构建器
        BoolQueryBuilder bq = buildWithEmailAndPhoneQuery(linkedInUserEs);

        // 构建ES请求
        EsSearchRequest esSearchRequest = new EsSearchRequest();
        esSearchRequest.setBq(bq);
        esSearchRequest.setFields(EsLinkedInFields.FIELD_QUERY);
        esSearchRequest.setFrom(0L);
        esSearchRequest.setSize(0L);
        esSearchRequest.setNeedScroll(false);
        esSearchRequest.setTrackTotalHits(true); // 确保获取精确计数

        SearchResponse searchResponse =
                EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

        if (searchResponse != null) {
            return Objects.requireNonNull(searchResponse.getHits().getTotalHits()).value;
        }

        return 0L;
    }

    @Override
    public List<Map<String, String>> findByDomain(String domain, int size, int offset) {
        LinkedInUserEs linkedInUserEs = new LinkedInUserEs();
        linkedInUserEs.setCompanyWebsite(domain);
        // 使用基础查询构建器
        BoolQueryBuilder boolQuery = buildBaseQuery(linkedInUserEs);

        return executeEsSearchForIdentifiers(boolQuery, size, offset);

    }

    @Override
    public List<Map<String, String>> findByKeyword(String keyword, int size, int offset) {
        LinkedInUserEs linkedInUserEs = new LinkedInUserEs();
        linkedInUserEs.setFullName(keyword);
        linkedInUserEs.setLinkedinUrl(keyword);
        linkedInUserEs.setCompanyName(keyword);
        linkedInUserEs.setTwitterUserName(keyword);
        linkedInUserEs.setFacebookUrl(keyword);
        linkedInUserEs.setGithubUrl(keyword);
        linkedInUserEs.setTwitterUrl(keyword);

        BoolQueryBuilder boolQuery = buildShouldQuery(linkedInUserEs);

        return executeEsSearchForIdentifiers(boolQuery, size, offset);

    }

    @Override
    public List<Map<String, String>> searchLinkedInByNameOrUrl(String keyword, int size, int offset) {
        LinkedInUserEs linkedInUserEs = new LinkedInUserEs();
        linkedInUserEs.setFullName(keyword);
        linkedInUserEs.setLinkedinUrl(keyword);
        linkedInUserEs.setTwitterUserName(keyword);

        BoolQueryBuilder boolQuery = buildShouldQuery(linkedInUserEs);

        return executeEsSearchForIdentifiers(boolQuery, size, offset);
    }
    
    @Override
    public List<Map<String, String>> searchByLinkedInUrlAndName(String linkedinUrl, String name, int limit, int offset) {
        log.info("ES两阶段查询 - 领英链接+姓名: linkedinUrl={}, name={}, limit={}", linkedinUrl, name, limit);
        
        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            
            // 领英链接或姓名至少匹配一个
            BoolQueryBuilder shouldQuery = QueryBuilders.boolQuery();
            
            if (linkedinUrl != null && !linkedinUrl.trim().isEmpty()) {
                shouldQuery.should(QueryBuilders.termQuery(EsLinkedInFields.LINKEDIN_URL, linkedinUrl));
            }
            
            if (name != null && !name.trim().isEmpty()) {
                shouldQuery.should(QueryBuilders.matchQuery(EsLinkedInFields.FULL_NAME + ".keyword", name));
            }
            
            shouldQuery.minimumShouldMatch(1);
            boolQuery.must(shouldQuery);
            
            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 100), offset);
            
        } catch (Exception e) {
            log.error("ES查询失败 - 领英链接+姓名: linkedinUrl={}, name={}, error={}", linkedinUrl, name, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public long countLinkedInUsersByKeyword(LinkedInUserEs linkedInUserEs) {
        try {
            log.info("🔍 开始ES计数查询: linkedInUserEs={}", JSON.toJSONString(linkedInUserEs));

            // 1. 构建计数请求
            EsSearchRequest esCountRequest = createEsCountByKeyWordRequest(linkedInUserEs);

            // 2. 执行计数查询
            SearchResponse searchResponse =
                    EsRestClient.searchWithTermQuery(getEsIndexInfo(), esCountRequest);

            // 3. 获取并返回精确计数
            long totalCount = searchResponse.getHits().getTotalHits().value;
            String relation = searchResponse.getHits().getTotalHits().relation.toString();

            log.info("🔍 ES计数查询结果: totalCount={}, relation={}, trackTotalHits生效={}",
                    totalCount, relation, esCountRequest.isTrackTotalHits());

            return totalCount;

        } catch (Exception e) {
            log.error("ES计数查询失败", e);
            return 0L;
        }
    }

    @Override
    public List<String> searchCompanies(String company) {
        // 使用Set自动去重
        Set<String> uniqueCities = new HashSet<>();

        BoolQueryBuilder bq = new BoolQueryBuilder();
        bq.should(QueryBuilders.wildcardQuery(EsLinkedInFields.COMPANY_NAME,   company + "*"));
        bq.should(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_NAME, company).fuzziness("AUTO"));
// 执行搜索并获取城市列表
        List<Map<String, Object>> results = executeEsSearchForCompanies(bq, company);
// 提取并去重城市名称
        for (Map<String, Object> result : results) {
            Object cityObj = result.get(EsLinkedInFields.COMPANY_NAME);
            if (cityObj != null) {
                if (cityObj instanceof String) {
                    uniqueCities.add((String) cityObj);
                } else if (cityObj instanceof List) {
                    for (Object item : (List<?>) cityObj) {
                        if (item instanceof String) {
                            uniqueCities.add((String) item);
                        }
                    }
                }
            }
        }

        // 转换为列表并返回
        return new ArrayList<>(uniqueCities);
    }

    @Override
    public List<String> searchJobTitles(String jobTitles) {
        // 使用Set自动去重
        Set<String> uniqueCities = new HashSet<>();

        BoolQueryBuilder bq = new BoolQueryBuilder();
        bq.should(QueryBuilders.wildcardQuery(EsLinkedInFields.JOB_TITLE,   jobTitles + "*"));
        bq.should(QueryBuilders.matchQuery(EsLinkedInFields.JOB_TITLE, jobTitles).fuzziness("AUTO"));
// 执行搜索并获取城市列表
        List<Map<String, Object>> results = executeEsSearchForJobTitles(bq, jobTitles);
// 提取并去重城市名称
        for (Map<String, Object> result : results) {
            Object cityObj = result.get(EsLinkedInFields.JOB_TITLE);
            if (cityObj != null) {
                if (cityObj instanceof String) {
                    uniqueCities.add((String) cityObj);
                } else if (cityObj instanceof List) {
                    for (Object item : (List<?>) cityObj) {
                        if (item instanceof String) {
                            uniqueCities.add((String) item);
                        }
                    }
                }
            }
        }

        // 转换为列表并返回
        return new ArrayList<>(uniqueCities);
    }

    @Override
    public List<String> searchIndustries(String industry) {
        // 使用Set自动去重
        Set<String> uniqueCities = new HashSet<>();

        BoolQueryBuilder bq = new BoolQueryBuilder();
        bq.should(QueryBuilders.wildcardQuery(EsLinkedInFields.COMPANY_INDUSTRY,   industry + "*"));
        bq.should(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_INDUSTRY, industry).fuzziness("AUTO"));
// 执行搜索并获取城市列表
        List<Map<String, Object>> results = executeEsSearchForIndustry(bq, industry);
// 提取并去重城市名称
        for (Map<String, Object> result : results) {
            Object cityObj = result.get(EsLinkedInFields.COMPANY_INDUSTRY);
            if (cityObj != null) {
                if (cityObj instanceof String) {
                    uniqueCities.add((String) cityObj);
                } else if (cityObj instanceof List) {
                    for (Object item : (List<?>) cityObj) {
                        if (item instanceof String) {
                            uniqueCities.add((String) item);
                        }
                    }
                }
            }
        }

        // 转换为列表并返回
        return new ArrayList<>(uniqueCities);
    }

    @Override
    public List<String> searchLocations(String location) {
        // 使用Set自动去重
        Set<String> uniqueCities = new HashSet<>();

        BoolQueryBuilder bq = new BoolQueryBuilder();
        bq.should(QueryBuilders.wildcardQuery(EsLinkedInFields.LOCATION,   location + "*"));
        bq.should(QueryBuilders.matchQuery(EsLinkedInFields.LOCATION, location).fuzziness("AUTO"));
// 执行搜索并获取城市列表
        List<Map<String, Object>> results = executeEsSearchForLocation(bq, location);
// 提取并去重城市名称
        for (Map<String, Object> result : results) {
            Object cityObj = result.get(EsLinkedInFields.LOCATION);
            if (cityObj != null) {
                if (cityObj instanceof String) {
                    uniqueCities.add((String) cityObj);
                } else if (cityObj instanceof List) {
                    for (Object item : (List<?>) cityObj) {
                        if (item instanceof String) {
                            uniqueCities.add((String) item);
                        }
                    }
                }
            }
        }

        // 转换为列表并返回
        return new ArrayList<>(uniqueCities);
    }

    @Override
    public List<LinkedInUserEs> searchLinkedInDataByPhone(String companyName, String fullName, String website) {

        LinkedInUserEs linkedInUserEs = new LinkedInUserEs();
        linkedInUserEs.setFullName(fullName);
        linkedInUserEs.setCompanyName(companyName);
        linkedInUserEs.setCompanyWebsite(website);
        linkedInUserEs.setContactMethod("phone");

        log.info("🔍 开始ES查询: linkedInUserEs={}", JSON.toJSONString(linkedInUserEs));
        // 1. 构建查询请求
        BoolQueryBuilder bq = buildByEmailAndPhoneQueryData(linkedInUserEs);

        EsSearchRequest esSearchRequest = new EsSearchRequest();
        esSearchRequest.setBq(bq);
        esSearchRequest.setFields(EsLinkedInFields.FIELD_QUERY);

        // 使用普通分页查询，限制最多返回5000条，避免查询过多数据
        esSearchRequest.setNeedScroll(false); // 不使用Scroll，使用普通查询
        esSearchRequest.setFrom(0L); // 设置起始位置
        esSearchRequest.setSize(5000L); // 最多返回5000条记录

        log.info("执行LinkedIn ES查询，限制最多返回5000条结果");

        // 2. 执行查询
        // 使用普通查询而非scroll查询
        SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

        List<LinkedInUserEs> linkedInUserEsList = new LinkedList<>();
        if (searchResponse != null && searchResponse.getHits() != null) {
            SearchHits hits = searchResponse.getHits();
            log.info("Twitter ES查询完成，共找到{}条匹配数据", hits.getTotalHits().value);

            for (SearchHit hit : hits.getHits()) {
                LinkedInUserEs user = convertResultFromMap(hit.getSourceAsMap());
                if (user != null) {
                    linkedInUserEsList.add(user);
                }
            }
        }

        return linkedInUserEsList;

    }

    private BoolQueryBuilder buildByEmailAndPhoneQueryData(LinkedInUserEs req) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 姓名搜索
        if (req.getFullName() != null && !req.getFullName().trim().isEmpty()) {
            boolQuery.must(QueryBuilders.termQuery(
                    EsLinkedInFields.FULL_NAME + ".keyword", req.getFullName().trim()));
        }

        // 公司名称筛选
        if (req.getCompanyName() != null && !req.getCompanyName().trim().isEmpty()) {
            boolQuery.must(QueryBuilders.termQuery(
                    EsLinkedInFields.COMPANY_NAME + ".keyword", req.getCompanyName().trim()));
        }

        // 公司网址
        if (req.getCompanyWebsite() != null && !req.getCompanyWebsite().trim().isEmpty()) {
            boolQuery.must(QueryBuilders.matchQuery(
                    EsLinkedInFields.COMPANY_WEBSITE, req.getCompanyWebsite().trim()));
        }

        // 必须满足的联系方式条件
        BoolQueryBuilder contactQuery = QueryBuilders.boolQuery();
        if (req.getContactMethod().contains("email")) {
            contactQuery
                    .should(QueryBuilders.existsQuery(EsLinkedInFields.EMAILS))
                    .should(QueryBuilders.wildcardQuery(EsLinkedInFields.EMAILS, "*"))
                    .minimumShouldMatch(1);
        }
        if (req.getContactMethod().contains("phone")) {
            contactQuery
                    .should(QueryBuilders.existsQuery(EsLinkedInFields.MOBILE))
                    .should(QueryBuilders.wildcardQuery(EsLinkedInFields.MOBILE, "*"))
                    .minimumShouldMatch(1);
        }
        boolQuery.must(contactQuery);


        return boolQuery;
    }

    @Override
    public List<LinkedInUserEs> searchLinkedInDataByEmail(String companyName, String fullName, String website) {

        LinkedInUserEs linkedInUserEs = new LinkedInUserEs();
        linkedInUserEs.setFullName(fullName);
        linkedInUserEs.setCompanyName(companyName);
        linkedInUserEs.setCompanyWebsite(website);
        linkedInUserEs.setContactMethod("email");

        log.info("🔍 开始ES查询: linkedInUserEs={}", JSON.toJSONString(linkedInUserEs));
        // 1. 构建查询请求
        BoolQueryBuilder bq = buildByEmailAndPhoneQueryData(linkedInUserEs);

        EsSearchRequest esSearchRequest = new EsSearchRequest();
        esSearchRequest.setBq(bq);
        esSearchRequest.setFields(EsLinkedInFields.FIELD_QUERY);


        // 使用普通分页查询，限制最多返回5000条，避免查询过多数据
        esSearchRequest.setNeedScroll(false); // 不使用Scroll，使用普通查询
        esSearchRequest.setFrom(0L); // 设置起始位置
        esSearchRequest.setSize(5000L); // 最多返回5000条记录

        log.info("执行LinkedIn ES查询，限制最多返回5000条结果");

        // 2. 执行查询
        // 使用普通查询而非scroll查询
        SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

        List<LinkedInUserEs> linkedInUserEsList = new LinkedList<>();
        if (searchResponse != null && searchResponse.getHits() != null) {
            SearchHits hits = searchResponse.getHits();
            log.info("LinkedIn ES查询完成，共找到{}条匹配数据", hits.getTotalHits().value);

            for (SearchHit hit : hits.getHits()) {
                LinkedInUserEs user = convertResultFromMap(hit.getSourceAsMap());
                if (user != null) {
                    linkedInUserEsList.add(user);
                }
            }
        }

        return linkedInUserEsList;

    }

    private List<Map<String, Object>> executeEsSearchForLocation(BoolQueryBuilder boolQuery, String location) {
        List<Map<String, Object>> results = new ArrayList<>();
        final int MAX_RESULTS = 20; // 限制最大结果数

        try {
            // 创建ES搜索请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom(0L);
            esSearchRequest.setSize((long) MAX_RESULTS);
            esSearchRequest.setNeedScroll(false);

            // 只查询当前所在地字段
            String[] fields = {EsLinkedInFields.LOCATION};
            esSearchRequest.setFields(fields);

            // 执行查询
            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse == null) {
                log.warn("ES查询返回null响应");
                return results;
            }

            SearchHits searchHits = searchResponse.getHits();
            if (searchHits == null || searchHits.getHits() == null) {
                log.warn("ES查询返回空结果");
                return results;
            }

            SearchHit[] hits = searchHits.getHits();
            log.info("ES查询返回{}条匹配记录", hits.length);

            // 提取城市信息
            for (SearchHit hit : hits) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                if (sourceAsMap != null && sourceAsMap.containsKey(EsLinkedInFields.LOCATION)) {
                    results.add(sourceAsMap);
                }
            }

            log.info("ES查询完成，有效匹配记录数: {}", results.size());
            return results;

        } catch (Exception e) {
            log.error("执行ES查询失败: {}", e.getMessage(), e);
            return results;
        }
    }

    private List<Map<String, Object>> executeEsSearchForIndustry(BoolQueryBuilder boolQuery, String industry) {
        List<Map<String, Object>> results = new ArrayList<>();
        final int MAX_RESULTS = 20; // 限制最大结果数

        try {
            // 创建ES搜索请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom(0L);
            esSearchRequest.setSize((long) MAX_RESULTS);
            esSearchRequest.setNeedScroll(false);

            // 只查询当前所在地字段
            String[] fields = {EsLinkedInFields.COMPANY_INDUSTRY};
            esSearchRequest.setFields(fields);

            // 执行查询
            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse == null) {
                log.warn("ES查询返回null响应");
                return results;
            }

            SearchHits searchHits = searchResponse.getHits();
            if (searchHits == null || searchHits.getHits() == null) {
                log.warn("ES查询返回空结果");
                return results;
            }

            SearchHit[] hits = searchHits.getHits();
            log.info("ES查询返回{}条匹配记录", hits.length);

            // 提取城市信息
            for (SearchHit hit : hits) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                if (sourceAsMap != null && sourceAsMap.containsKey(EsLinkedInFields.COMPANY_INDUSTRY)) {
                    results.add(sourceAsMap);
                }
            }

            log.info("ES查询完成，有效匹配记录数: {}", results.size());
            return results;

        } catch (Exception e) {
            log.error("执行ES查询失败: {}", e.getMessage(), e);
            return results;
        }
    }

    private List<Map<String, Object>> executeEsSearchForJobTitles(BoolQueryBuilder boolQuery, String jobTitles) {
        List<Map<String, Object>> results = new ArrayList<>();
        final int MAX_RESULTS = 20; // 限制最大结果数

        try {
            // 创建ES搜索请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom(0L);
            esSearchRequest.setSize((long) MAX_RESULTS);
            esSearchRequest.setNeedScroll(false);

            // 只查询当前所在地字段
            String[] fields = {EsLinkedInFields.JOB_TITLE};
            esSearchRequest.setFields(fields);

            // 执行查询
            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse == null) {
                log.warn("ES查询返回null响应");
                return results;
            }

            SearchHits searchHits = searchResponse.getHits();
            if (searchHits == null || searchHits.getHits() == null) {
                log.warn("ES查询返回空结果");
                return results;
            }

            SearchHit[] hits = searchHits.getHits();
            log.info("ES查询返回{}条匹配记录", hits.length);

            // 提取城市信息
            for (SearchHit hit : hits) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                if (sourceAsMap != null && sourceAsMap.containsKey(EsLinkedInFields.JOB_TITLE)) {
                    results.add(sourceAsMap);
                }
            }

            log.info("ES查询完成，有效匹配记录数: {}", results.size());
            return results;

        } catch (Exception e) {
            log.error("执行ES查询失败: {}", e.getMessage(), e);
            return results;
        }
    }

    private List<Map<String, Object>> executeEsSearchForCompanies(BoolQueryBuilder boolQuery, String company) {
        List<Map<String, Object>> results = new ArrayList<>();
        final int MAX_RESULTS = 20; // 限制最大结果数

        try {
            // 创建ES搜索请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom(0L);
            esSearchRequest.setSize((long) MAX_RESULTS);
            esSearchRequest.setNeedScroll(false);

            // 只查询当前所在地字段
            String[] fields = {EsLinkedInFields.COMPANY_NAME};
            esSearchRequest.setFields(fields);

            // 执行查询
            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse == null) {
                log.warn("ES查询返回null响应");
                return results;
            }

            SearchHits searchHits = searchResponse.getHits();
            if (searchHits == null || searchHits.getHits() == null) {
                log.warn("ES查询返回空结果");
                return results;
            }

            SearchHit[] hits = searchHits.getHits();
            log.info("ES查询返回{}条匹配记录", hits.length);

            // 提取城市信息
            for (SearchHit hit : hits) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                if (sourceAsMap != null && sourceAsMap.containsKey(EsLinkedInFields.COMPANY_NAME)) {
                    results.add(sourceAsMap);
                }
            }

            log.info("ES查询完成，有效匹配记录数: {}", results.size());
            return results;

        } catch (Exception e) {
            log.error("执行ES查询失败: {}", e.getMessage(), e);
            return results;
        }
    }

    private EsSearchRequest createEsCountByKeyWordRequest(LinkedInUserEs linkedInUserEs) {
        BoolQueryBuilder bq = buildShouldQuery(linkedInUserEs);

        EsSearchRequest esCountRequest = new EsSearchRequest();
        esCountRequest.setBq(bq);
        esCountRequest.setFrom(0L);
        esCountRequest.setSize(0L); // 只计数，不返回数据
        esCountRequest.setNeedScroll(false);
        esCountRequest.setTrackTotalHits(true); // 确保获取精确计数

        return esCountRequest;
    }

    private BoolQueryBuilder buildShouldQuery(LinkedInUserEs req) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 姓名搜索
        if (req.getFullName() != null && !req.getFullName().trim().isEmpty()) {
            BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
            keywordQuery.must(QueryBuilders.termQuery(EsLinkedInFields.FULL_NAME + ".keyword", req.getFullName()));
            boolQuery.should(keywordQuery);
        }

        // 公司名称筛选
        if (req.getCompanyName() != null && !req.getCompanyName().trim().isEmpty()) {
                boolQuery.should(QueryBuilders.termQuery(EsLinkedInFields.COMPANY_NAME + ".keyword", req.getCompanyName()));
        }

        if (req.getTwitterUserName() != null && !req.getTwitterUserName().trim().isEmpty()) {
            boolQuery.should(QueryBuilders.termQuery(EsLinkedInFields.TWITTER_USERNAME, req.getTwitterUserName()));
        }

        if (req.getTwitterUrl() != null && !req.getTwitterUrl().trim().isEmpty()) {
            boolQuery.should(QueryBuilders.wildcardQuery(EsLinkedInFields.TWITTER_URL, "*" + req.getTwitterUrl()));
        }

        if (req.getGithubUrl() != null && !req.getGithubUrl().trim().isEmpty()) {
            boolQuery.should(QueryBuilders.wildcardQuery(EsLinkedInFields.GITHUB_URL, "*" + req.getGithubUrl()));
        }

        if (req.getFacebookUrl() != null && !req.getFacebookUrl().trim().isEmpty()) {
            boolQuery.should(QueryBuilders.wildcardQuery(EsLinkedInFields.FACEBOOK_URL, "*" + req.getFacebookUrl()));
        }

        if (req.getLinkedinUrl() != null && !req.getLinkedinUrl().trim().isEmpty()) {
            boolQuery.should(QueryBuilders.wildcardQuery(EsLinkedInFields.LINKEDIN_URL, "*" + req.getLinkedinUrl()));
        }

        return boolQuery;
    }

    private BoolQueryBuilder buildWithEmailAndPhoneQuery(LinkedInUserEs req) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        BoolQueryBuilder optionalFieldsQuery = QueryBuilders.boolQuery();

        // 姓名搜索
        if (req.getFullName() != null && !req.getFullName().trim().isEmpty()) {
            optionalFieldsQuery.should(QueryBuilders.matchQuery(
                    EsLinkedInFields.FULL_NAME, req.getFullName().trim()));
        }

        // 公司名称筛选
        if (req.getCompanyName() != null && !req.getCompanyName().trim().isEmpty()) {
            optionalFieldsQuery.should(QueryBuilders.matchQuery(
                    EsLinkedInFields.COMPANY_NAME, req.getCompanyName().trim()));
        }

        // 公司网址
        if (req.getCompanyWebsite() != null && !req.getCompanyWebsite().trim().isEmpty()) {
            optionalFieldsQuery.should(QueryBuilders.termQuery(
                    EsLinkedInFields.COMPANY_WEBSITE, req.getCompanyWebsite().trim()));
        }

        // 必须满足的联系方式条件
        BoolQueryBuilder contactQuery = QueryBuilders.boolQuery();
        if (req.getContactMethod().contains("email")) {
            contactQuery
                    .should(QueryBuilders.existsQuery(EsLinkedInFields.EMAILS))
                    .should(QueryBuilders.wildcardQuery(EsLinkedInFields.EMAILS, "*"))
                    .minimumShouldMatch(1);
        }
        if (req.getContactMethod().contains("phone")) {
            contactQuery
                    .should(QueryBuilders.existsQuery(EsLinkedInFields.MOBILE))
                    .should(QueryBuilders.wildcardQuery(EsLinkedInFields.MOBILE, "*"))
                    .minimumShouldMatch(1);
        }
        boolQuery.must(contactQuery);

        // 如果有可选字段条件，添加到主查询中
        if (!optionalFieldsQuery.should().isEmpty()) {
            boolQuery.must(optionalFieldsQuery);
        }


        return boolQuery;
    }

    // ==================== 私有辅助方法 ====================

    /**
     * 构建基础查询条件
     */
    private BoolQueryBuilder buildBaseQuery(LinkedInUserEs req) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 姓名搜索
        if (req.getFullName() != null && !req.getFullName().trim().isEmpty()) {
            if (req.getFullName().contains(" ")) {
                BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
                keywordQuery.must(QueryBuilders.termQuery(EsLinkedInFields.SORT_FIELD_NAME, req.getFullName()));
                boolQuery.must(keywordQuery);
            } else {
                BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
                keywordQuery.should(QueryBuilders.matchQuery(EsLinkedInFields.FULL_NAME, req.getFullName()));
                boolQuery.must(keywordQuery);
            }
        }

        // 公司名称筛选
        if (req.getCompanyName() != null && !req.getCompanyName().trim().isEmpty()) {
            if (req.getCompanyName().contains(",")) {
                BoolQueryBuilder companyNameQuery = QueryBuilders.boolQuery();
                String[] companyNames = req.getCompanyName().split(",");
                for (String name : companyNames) {
                    companyNameQuery.should(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_NAME, name.trim()));
                }
                boolQuery.must(companyNameQuery);
            } else {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_NAME, req.getCompanyName()));
            }
        }

        // 职位筛选
        if (req.getJobTitle() != null && !req.getJobTitle().trim().isEmpty()) {
            if (req.getJobTitle().contains(",")){
                BoolQueryBuilder jobTitleQuery = QueryBuilders.boolQuery();
                String[] jobTitles = req.getJobTitle().split(",");
                for (String title : jobTitles) {
                    jobTitleQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_JOB_TITLE, title.trim()));
                }
                boolQuery.must(jobTitleQuery);
            }else {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.AGG_JOB_TITLE, req.getJobTitle()));
            }
        }

        // 行业筛选
        if (req.getCompanyIndustry() != null && !req.getCompanyIndustry().trim().isEmpty()) {
            if ( req.getCompanyIndustry().contains(",")) {
                BoolQueryBuilder industryQuery = QueryBuilders.boolQuery();
                String[] industries =  req.getCompanyIndustry().split(",");
                for (String ind : industries) {
                    industryQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_INDUSTRY, ind.trim()));
                }
                boolQuery.must(industryQuery);
            } else {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.AGG_INDUSTRY, req.getCompanyIndustry()));
            }
        }

        // 位置筛选
        if (req.getCountry() != null && !req.getCountry().trim().isEmpty()) {
            if (req.getCountry().contains(",")) {
                BoolQueryBuilder locationQuery = QueryBuilders.boolQuery();
                String[] locations = req.getCountry().split(",");
                for (String loc : locations) {
                    locationQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_COUNTRY, loc.trim()));
                }
                boolQuery.must(locationQuery);
            } else {
                BoolQueryBuilder locationQuery = QueryBuilders.boolQuery();
                locationQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_COUNTRY, req.getCountry().trim()));

                boolQuery.must(locationQuery);
            }
        }

        // 联系方式筛选
        if (req.getContactMethod() != null && !req.getContactMethod().trim().isEmpty()) {
            BoolQueryBuilder contactQuery = QueryBuilders.boolQuery();
            if (req.getContactMethod().contains("email")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.EMAILS))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.EMAILS, ""));
            }
            if (req.getContactMethod().contains("phone")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.MOBILE))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.MOBILE, ""));
            }
            if (req.getContactMethod().contains("companyWebsite")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.COMPANY_WEBSITE))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.COMPANY_WEBSITE, ""));
            }
            if (req.getContactMethod().contains("linkedin")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.LINKEDIN_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.LINKEDIN_URL, ""));
            }
            if (req.getContactMethod().contains("facebookUrl")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.FACEBOOK_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.FACEBOOK_URL, ""));
            }
            if (req.getContactMethod().contains("twitterUrl")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.TWITTER_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.TWITTER_URL, ""));
            }
            if (req.getContactMethod().contains("githubUrl")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.GITHUB_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.GITHUB_URL, ""));
            }

            boolQuery.must(contactQuery);
        }

        if (req.getEmails() != null && !req.getEmails().trim().isEmpty()){
            boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.EMAILS, req.getEmails()));
        }

        if (req.getPhoneNumbers() != null && !req.getPhoneNumbers().trim().isEmpty()){
            boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.PHONE_NUMBERS, req.getPhoneNumbers()));
        }

        if (req.getCompanyWebsite() != null && !req.getCompanyWebsite().trim().isEmpty()){
            boolQuery.must(QueryBuilders.wildcardQuery(EsLinkedInFields.COMPANY_WEBSITE, "*" + req.getCompanyWebsite()));
        }

        return boolQuery;
    }

    /**
     * 构建导出查询条件
     */
    private BoolQueryBuilder buildExportQuery(LinkedInQueryDTO queryDTO) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 姓名搜索
        if (queryDTO.getFullName() != null && !queryDTO.getFullName().trim().isEmpty()) {
            if (queryDTO.getFullName().contains(" ")) {
                BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
                keywordQuery.must(QueryBuilders.termQuery(EsLinkedInFields.SORT_FIELD_NAME, queryDTO.getFullName()));
                boolQuery.must(keywordQuery);
            } else {
                BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
                keywordQuery.should(QueryBuilders.matchQuery(EsLinkedInFields.FULL_NAME, queryDTO.getFullName()));
                boolQuery.must(keywordQuery);
            }
        }

        // 公司名称筛选
        if (queryDTO.getCompanyName() != null && !queryDTO.getCompanyName().trim().isEmpty()) {
            if (queryDTO.getCompanyName().contains(",")) {
                BoolQueryBuilder companyNameQuery = QueryBuilders.boolQuery();
                String[] companyNames = queryDTO.getCompanyName().split(",");
                for (String name : companyNames) {
                    companyNameQuery.should(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_NAME, name.trim()));
                }
                boolQuery.must(companyNameQuery);
            } else {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_NAME, queryDTO.getCompanyName()));
            }        }

        // 职位筛选
        if (queryDTO.getJobTitle() != null && !queryDTO.getJobTitle().trim().isEmpty()) {
            if (queryDTO.getJobTitle().contains(",")){
                BoolQueryBuilder jobTitleQuery = QueryBuilders.boolQuery();
                String[] jobTitles = queryDTO.getJobTitle().split(",");
                for (String title : jobTitles) {
                    jobTitleQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_JOB_TITLE, title.trim()));
                }
                boolQuery.must(jobTitleQuery);
            }else {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.AGG_JOB_TITLE, queryDTO.getJobTitle()));
            }
        }

        // 行业筛选
        if (queryDTO.getIndustry() != null && !queryDTO.getIndustry().trim().isEmpty()) {
            if (queryDTO.getIndustry().contains(",")) {
                BoolQueryBuilder industryQuery = QueryBuilders.boolQuery();
                String[] industries = queryDTO.getIndustry().split(",");
                for (String ind : industries) {
                    industryQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_INDUSTRY, ind.trim()));
                }
                boolQuery.must(industryQuery);
            } else {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.AGG_INDUSTRY, queryDTO.getIndustry()));
            }
        }

        // 位置筛选
        if (queryDTO.getCountry() != null && !queryDTO.getCountry().trim().isEmpty()) {
            if (queryDTO.getCountry().contains(",")) {
                BoolQueryBuilder locationQuery = QueryBuilders.boolQuery();
                String[] locations = queryDTO.getCountry().split(",");
                for (String loc : locations) {
                    locationQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_COUNTRY, loc.trim()));
                }
                boolQuery.must(locationQuery);
            } else {
                BoolQueryBuilder locationQuery = QueryBuilders.boolQuery();
                locationQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_COUNTRY, queryDTO.getCountry().trim()));

                boolQuery.must(locationQuery);
            }
        }

        // 联系方式筛选
        if (queryDTO.getContactMethod() != null && !queryDTO.getContactMethod().trim().isEmpty()) {
            BoolQueryBuilder contactQuery = QueryBuilders.boolQuery();
            if(queryDTO.getContactMethod().contains("email")){
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.EMAILS))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.EMAILS, ""));
            }
            if(queryDTO.getContactMethod().contains("phone")){
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.MOBILE))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.MOBILE, ""));
            }
            if(queryDTO.getContactMethod().contains("companyWebsite")){
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.COMPANY_WEBSITE))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.COMPANY_WEBSITE, ""));
            }
            if(queryDTO.getContactMethod().contains("linkedin")){
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.LINKEDIN_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.LINKEDIN_URL, ""));
            }
            if (queryDTO.getContactMethod().contains("facebookUrl")){
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.FACEBOOK_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.FACEBOOK_URL, ""));
            }
            if (queryDTO.getContactMethod().contains("twitterUrl")){
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.TWITTER_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.TWITTER_URL, ""));
            }
            if (queryDTO.getContactMethod().contains("githubUrl")){
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.GITHUB_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.GITHUB_URL, ""));
            }

            boolQuery.must(contactQuery);
        }

        // 公司规模筛选
        if (queryDTO.getCompanySize() != null && !queryDTO.getCompanySize().trim().isEmpty()) {
            boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.COMPANY_SIZE, queryDTO.getCompanySize()));
        }

        return boolQuery;
    }

    /**
     * 构建筛选查询条件
     */
    private BoolQueryBuilder buildFilterQuery(String keyword, String companyName, String jobTitle,
                                              String industry, String location, String contactMethod,
                                              String companySize) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 姓名搜索
        if (keyword != null && !keyword.trim().isEmpty()) {
            if (keyword.contains(" ")) {
                BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
                keywordQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.SORT_FIELD_NAME, keyword));
                boolQuery.must(keywordQuery);
            } else{
                BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
                keywordQuery.should(QueryBuilders.matchQuery(EsLinkedInFields.FULL_NAME, keyword));
                boolQuery.must(keywordQuery);
            }
        }

        // 公司名称筛选
        if (companyName != null && !companyName.trim().isEmpty()) {
            if (companyName.contains(",")) {
                BoolQueryBuilder companyNameQuery = QueryBuilders.boolQuery();
                String[] companyNames = companyName.split(",");
                for (String name : companyNames) {
                    companyNameQuery.should(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_NAME, name.trim()));
                }
                boolQuery.must(companyNameQuery);
            } else {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.COMPANY_NAME, companyName));
            }
        }

        // 职位筛选
        if (jobTitle != null && !jobTitle.trim().isEmpty()) {
            if (jobTitle.contains(",")){
                BoolQueryBuilder jobTitleQuery = QueryBuilders.boolQuery();
                String[] jobTitles = jobTitle.split(",");
                for (String title : jobTitles) {
                    jobTitleQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_JOB_TITLE, title.trim()));
                }
                boolQuery.must(jobTitleQuery);
            }else {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.AGG_JOB_TITLE, jobTitle));
            }
        }

        // 行业筛选
        if (industry != null && !industry.trim().isEmpty()) {
            if (industry.contains(",")) {
                BoolQueryBuilder industryQuery = QueryBuilders.boolQuery();
                String[] industries = industry.split(",");
                for (String ind : industries) {
                    industryQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_INDUSTRY, ind.trim()));
                }
                boolQuery.must(industryQuery);
            } else {
                boolQuery.must(QueryBuilders.termQuery(EsLinkedInFields.AGG_INDUSTRY, industry));
            }
        }

        // 位置筛选
        if (location != null && !location.trim().isEmpty()) {
            if (location.contains(",")) {
                BoolQueryBuilder locationQuery = QueryBuilders.boolQuery();
                String[] locations = location.split(",");
                for (String loc : locations) {
                    locationQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_COUNTRY, loc.trim()));
                }
                boolQuery.must(locationQuery);
            } else {
                BoolQueryBuilder locationQuery = QueryBuilders.boolQuery();
                locationQuery.should(QueryBuilders.termQuery(EsLinkedInFields.AGG_COUNTRY, location.trim()));

                boolQuery.must(locationQuery);
            }
        }

        // 联系方式筛选
        if (contactMethod != null && !contactMethod.trim().isEmpty()) {
            BoolQueryBuilder contactQuery = QueryBuilders.boolQuery();
            if (contactMethod.contains("email")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.EMAILS))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.EMAILS, ""));
            }
            if (contactMethod.contains("phone")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.MOBILE))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.MOBILE, ""));
            }
            if (contactMethod.contains("companyWebsite")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.COMPANY_WEBSITE))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.COMPANY_WEBSITE, ""));
            }
            if (contactMethod.contains("linkedin")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.LINKEDIN_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.LINKEDIN_URL, ""));
            }
            if (contactMethod.contains("facebookUrl")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.FACEBOOK_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.FACEBOOK_URL, ""));
            }
            if (contactMethod.contains("twitterUrl")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.TWITTER_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.TWITTER_URL, ""));
            }
            if (contactMethod.contains("githubUrl")) {
                contactQuery
                        .must(QueryBuilders.existsQuery(EsLinkedInFields.GITHUB_URL))
                        .mustNot(QueryBuilders.termQuery(EsLinkedInFields.GITHUB_URL, ""));
            }
            boolQuery.must(contactQuery);

        }

        if (StringUtils.hasText(companySize)) {
            if (companySize.contains(",")) {
                BoolQueryBuilder companySizeQuery = QueryBuilders.boolQuery();
                String[] companySizes = companySize.split(",");
                for (String size : companySizes) {
                    companySizeQuery.should(QueryBuilders.matchQuery(EsLinkedInFields.AGG_COMPANY_SIZE, size.trim()));
                }
                boolQuery.must(companySizeQuery);
            } else {
                boolQuery.must(QueryBuilders.matchQuery(EsLinkedInFields.AGG_COMPANY_SIZE, companySize));
            }
        }

        return boolQuery;
    }

    /**
     * 执行ES查询获取标识信息
     */
    private List<Map<String, String>> executeEsSearchForIdentifiers(BoolQueryBuilder boolQuery, int limit, int offset) {
        List<Map<String, String>> results = new ArrayList<>();

        try {
            // 创建ES搜索请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom((long) offset);
            esSearchRequest.setSize((long) limit);
            esSearchRequest.setNeedScroll(false);

            // 添加排序规则，确保与分页查询一致
            esSearchRequest.setSortName(EsLinkedInFields.SORT_FIELD_PRIMARY);
            esSearchRequest.setSortOrder(EsLinkedInFields.SORT_ORDER_NEWEST_FIRST);

            // 只查询必要的字段以提升性能
            String[] fields = {EsLinkedInFields.MYSQL_TABLE, EsLinkedInFields.MYSQL_ID};
            esSearchRequest.setFields(fields);

            log.debug("执行ES查询，条件: {}, limit: {}, sort: {}:{}", boolQuery.toString(), limit,
                    EsLinkedInFields.SORT_FIELD_PRIMARY, EsLinkedInFields.SORT_ORDER_NEWEST_FIRST);

            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse != null && searchResponse.getHits() != null) {
                SearchHit[] hits = searchResponse.getHits().getHits();
                log.info("ES查询返回 {} 条匹配记录", hits.length);

                for (SearchHit hit : hits) {
                    Map<String, Object> sourceMap = hit.getSourceAsMap();

                    // 使用安全的类型转换
                    String mysqlTable = safeGetString(sourceMap, EsLinkedInFields.MYSQL_TABLE);
                    String mysqlId = safeGetString(sourceMap, EsLinkedInFields.MYSQL_ID);

                    if (mysqlTable != null && mysqlId != null) {
                        Map<String, String> identifier = new HashMap<>();
                        identifier.put("mysqlTable", mysqlTable);
                        identifier.put("id", mysqlId);
                        results.add(identifier);

                        log.debug("提取标识信息: mysqlTable={}, id={}", mysqlTable, mysqlId);
                    } else {
                        log.warn("ES记录缺少必要的标识字段: mysqlTable={}, mysqlId={}, 原始数据类型: mysqlTable={}, mysqlId={}",
                                mysqlTable, mysqlId,
                                sourceMap.get(EsLinkedInFields.MYSQL_TABLE) != null ? sourceMap.get(EsLinkedInFields.MYSQL_TABLE).getClass().getSimpleName() : "null",
                                sourceMap.get(EsLinkedInFields.MYSQL_ID) != null ? sourceMap.get(EsLinkedInFields.MYSQL_ID).getClass().getSimpleName() : "null");
                    }
                }
            } else {
                log.warn("ES查询返回空结果");
            }

            log.info("ES查询完成，有效匹配记录数: {}", results.size());
            return results;

        } catch (Exception e) {
            log.error("执行ES查询失败: {}", e.getMessage(), e);
            return results;
        }
    }

    /**
     * 执行ES分页查询获取标识信息
     */
    private List<Map<String, String>> executeEsSearchForIdentifiersWithPagination(BoolQueryBuilder boolQuery, int from, int size) {
        List<Map<String, String>> results = new ArrayList<>();

        try {
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom((long) from);
            esSearchRequest.setSize((long) size);
            esSearchRequest.setNeedScroll(false);

            // 只查询必要的字段
            String[] fields = {EsLinkedInFields.MYSQL_TABLE, EsLinkedInFields.MYSQL_ID};
            esSearchRequest.setFields(fields);

            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse != null && searchResponse.getHits() != null) {
                SearchHit[] hits = searchResponse.getHits().getHits();
                for (SearchHit hit : hits) {
                    Map<String, Object> sourceMap = hit.getSourceAsMap();

                    // 使用安全的类型转换
                    String mysqlTable = safeGetString(sourceMap, EsLinkedInFields.MYSQL_TABLE);
                    String mysqlId = safeGetString(sourceMap, EsLinkedInFields.MYSQL_ID);

                    if (mysqlTable != null && mysqlId != null) {
                        Map<String, String> identifier = new HashMap<>();
                        identifier.put("mysqlTable", mysqlTable);
                        identifier.put("id", mysqlId);
                        results.add(identifier);
                    } else {
                        log.debug("分页查询中跳过无效记录: mysqlTable={}, mysqlId={}", mysqlTable, mysqlId);
                    }
                }
            }

            return results;

        } catch (Exception e) {
            log.error("执行ES分页查询失败: from={}, size={}, error={}", from, size, e.getMessage(), e);
            return results;
        }
    }

    /**
     * 创建ES计数请求
     */
    private EsSearchRequest createEsCountRequest(LinkedInUserEs linkedInUserEs) {
        BoolQueryBuilder bq = buildBaseQuery(linkedInUserEs);

        EsSearchRequest esCountRequest = new EsSearchRequest();
        esCountRequest.setBq(bq);
        esCountRequest.setFrom(0L);
        esCountRequest.setSize(0L); // 只计数，不返回数据
        esCountRequest.setNeedScroll(false);
        esCountRequest.setTrackTotalHits(true); // 确保获取精确计数

        return esCountRequest;
    }

    /**
     * 从Map直接转换为LinkedInUserEs对象（用于Scroll查询）
     */
    private LinkedInUserEs convertResultFromMap(Map<String, Object> sourceMap) {
        try {
            if (sourceMap == null || sourceMap.isEmpty()) {
                log.warn("sourceMap为空，无法转换");
                return null;
            }
            
            LinkedInUserEs linkedInUserEs = new LinkedInUserEs();

            // 基础标识字段 - 使用安全转换
            linkedInUserEs.setMId(safeGetString(sourceMap, EsLinkedInFields.MYSQL_ID));
            linkedInUserEs.setMt(safeGetString(sourceMap, EsLinkedInFields.MYSQL_TABLE));

            // 核心业务字段 - 使用安全转换
            linkedInUserEs.setCompanyName(safeGetString(sourceMap, EsLinkedInFields.COMPANY_NAME));
            linkedInUserEs.setJobTitle(safeGetString(sourceMap, EsLinkedInFields.JOB_TITLE));
            linkedInUserEs.setLocation(safeGetString(sourceMap, EsLinkedInFields.LOCATION));
            linkedInUserEs.setCompanyIndustry(safeGetString(sourceMap, EsLinkedInFields.COMPANY_INDUSTRY));
            linkedInUserEs.setLinkedinUrl(safeGetString(sourceMap, EsLinkedInFields.LINKEDIN_URL));
            linkedInUserEs.setEmails(safeGetString(sourceMap, EsLinkedInFields.EMAILS));
            linkedInUserEs.setCompanySize(safeGetString(sourceMap, EsLinkedInFields.COMPANY_SIZE));
            linkedInUserEs.setYearsExperience(safeGetString(sourceMap, EsLinkedInFields.YEARS_EXPERIENCE));

            // 个人信息字段 - 使用安全转换
            linkedInUserEs.setFullName(safeGetString(sourceMap, EsLinkedInFields.FULL_NAME));
            linkedInUserEs.setFirstName(safeGetString(sourceMap, EsLinkedInFields.FIRST_NAME));
            linkedInUserEs.setLastName(safeGetString(sourceMap, EsLinkedInFields.LAST_NAME));
            linkedInUserEs.setMobile(safeGetString(sourceMap, EsLinkedInFields.MOBILE));
            linkedInUserEs.setPhoneNumbers(safeGetString(sourceMap, EsLinkedInFields.MOBILE));
            linkedInUserEs.setCountry(safeGetString(sourceMap, EsLinkedInFields.COUNTRY));
            linkedInUserEs.setCity(safeGetString(sourceMap, EsLinkedInFields.CITY));

            // 扩展信息字段 - 使用安全转换
            linkedInUserEs.setCompanyWebsite(safeGetString(sourceMap, EsLinkedInFields.COMPANY_WEBSITE));
            linkedInUserEs.setCompanyFounded(safeGetString(sourceMap, EsLinkedInFields.COMPANY_FOUNDED));
            linkedInUserEs.setTwitterUserName(safeGetString(sourceMap, EsLinkedInFields.TWITTER_USERNAME));
            linkedInUserEs.setTwitterUrl(safeGetString(sourceMap, EsLinkedInFields.TWITTER_URL));
            linkedInUserEs.setGithubUrl(safeGetString(sourceMap, EsLinkedInFields.GITHUB_URL));
            linkedInUserEs.setFacebookUrl(safeGetString(sourceMap, EsLinkedInFields.FACEBOOK_URL));
            linkedInUserEs.setEducation(safeGetString(sourceMap, EsLinkedInFields.EDUCATION));
            linkedInUserEs.setSkills(safeGetString(sourceMap, EsLinkedInFields.SKILLS));

            // 添加调试日志，记录成功转换的记录
            log.debug("成功转换ES记录: mysqlId={}, companyName={}, jobTitle={}",
                    linkedInUserEs.getMId(), linkedInUserEs.getCompanyName(), linkedInUserEs.getJobTitle());

            return linkedInUserEs;

        } catch (Exception e) {
            log.error("从Map转换ES查询结果失败: error={}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 转换ES查询结果为LinkedInUserEs对象
     * 使用安全的类型转换，避免ClassCastException
     */
    private LinkedInUserEs convertResult(SearchHit hit) {
        Map<String, Object> sourceMap = hit.getSourceAsMap();
        return convertResultFromMap(sourceMap);
    }

    /**
     * 获取ES索引信息
     */
    private EsIndexInfo getEsIndexInfo() {
        EsIndexInfo esIndexInfo = new EsIndexInfo();
        esIndexInfo.setClusterName("my-es");
//        esIndexInfo.setClusterName("elasticsearch");
        esIndexInfo.setIndexName("ly_users"); // LinkedIn用户ES索引名称
        return esIndexInfo;
    }

    // ==================== 安全类型转换辅助方法 ====================

    /**
     * 安全地将Object转换为String
     * 处理null值和不同数据类型的转换
     */
    private String safeToString(Object value) {
        if (value == null) {
            return null;
        }

        // 如果已经是String类型，直接返回
        if (value instanceof String) {
            return (String) value;
        }

        // 处理数字类型（Integer, Long, Double, Float, BigDecimal等）
        if (value instanceof Number) {
            // 对于整数类型，不显示小数点
            if (value instanceof Integer || value instanceof Long) {
                return value.toString();
            }
            // 对于浮点数类型，保持原有格式
            return value.toString();
        }

        // 处理布尔类型
        if (value instanceof Boolean) {
            return value.toString();
        }

        // 处理数组类型
        if (value.getClass().isArray()) {
            return Arrays.toString((Object[]) value);
        }

        // 处理集合类型
        if (value instanceof Collection) {
            return value.toString();
        }

        // 记录未知类型的转换，便于调试
        log.debug("转换未知类型到String: type={}, value={}", value.getClass().getSimpleName(), value);

        // 其他类型统一转换为字符串
        return String.valueOf(value);
    }

    /**
     * 安全地从Map中获取String值
     */
    private String safeGetString(Map<String, Object> sourceMap, String fieldName) {
        try {
            if (sourceMap == null) {
                log.warn("sourceMap为null，无法获取字段: {}", fieldName);
                return null;
            }

            Object value = sourceMap.get(fieldName);
            if (value != null) {
                log.debug("字段 {} 的原始类型: {}, 值: {}", fieldName, value.getClass().getSimpleName(), value);
            }

            String result = safeToString(value);

            return result;
        } catch (Exception e) {
            log.error("获取字段值失败: fieldName={}, sourceMap={}, error={}", fieldName, sourceMap, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 安全地从Map中获取String值，带默认值
     */
    private String safeGetString(Map<String, Object> sourceMap, String fieldName, String defaultValue) {
        String value = safeGetString(sourceMap, fieldName);
        return value != null ? value : defaultValue;
    }

    /**
     * 测试类型转换功能（用于调试）
     */
    private void testTypeConversion() {
        log.info("=== 测试类型转换功能 ===");

        // 测试各种数据类型的转换
        Map<String, Object> testData = new HashMap<>();
        testData.put("stringField", "test string");
        testData.put("intField", 12345);
        testData.put("longField", 123456789L);
        testData.put("doubleField", 123.45);
        testData.put("booleanField", true);
        testData.put("nullField", null);

        for (Map.Entry<String, Object> entry : testData.entrySet()) {
            String fieldName = entry.getKey();
            Object originalValue = entry.getValue();
            String convertedValue = safeGetString(testData, fieldName);

            log.info("字段: {}, 原始类型: {}, 原始值: {}, 转换后: {}",
                    fieldName,
                    originalValue != null ? originalValue.getClass().getSimpleName() : "null",
                    originalValue,
                    convertedValue);
        }

        log.info("=== 类型转换测试完成 ===");
    }
}

